/*
 *  Copyright 2005 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.model.forum;

import com.blandware.atleap.model.core.BaseObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>Class that represents a forum topic.
 * </p>
 * <p><a href="Topic.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.3 $ $Date: 2007/12/24 15:53:38 $
 * @struts.form include-all="false" extends="PostForm"
 * @hibernate.class table="`al_forum_topic`" lazy="false"
 * @hibernate.cache usage="read-write"
 */
public class Topic extends BaseObject {

    /**
     * ID of topic.
     */
    protected Long id = null;

    /**
     * Forum to which this topic belongs
     */
    protected Forum forum = null;

    /**
     * Link to a first post that created this topic.
     */
    protected Post firstPost = null;

    /**
     * List of posts which belong to this topic
     */
    protected List posts = new ArrayList();

    /**
     * Version (used for optimistic locking)
     */
    protected Long version = null;

    /**
     * Number of replies in this topic (all posts except first one)
     */
    protected Integer numberOfReplies = null;

    /**
     * Last reply in this topic
     */
    protected Post lastReply = null;

    /**
     * This map maps username to <code>Boolean.TRUE</code> if and only if
     * that user is subscribed to this topic
     */
    protected Map usersSubscribed = new HashMap();

    /**
     * List of forum subscriptions that relate to this topic
     */
    protected List forumSubscriptions = new ArrayList();

    /**
     * Constructs a new Topic instance
     */
    public Topic() {
    }

    /**
     * Returns topic ID.
     *
     * @return ID
     * @struts.form-field
	 * @hibernate.id column="`id`"
	 * generator-class="increment" unsaved-value="null"
     */
    public Long getId() {
        return id;
    }

    /**
     * Sets topic ID.
     *
     * @param id ID to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns a forum to which this forum belongs
     *
     * @return owner forum
     * @struts.form-field
	 * @hibernate.many-to-one column="`forum_id`" not-null="true"
     * outer-join="false" lazy="false"
     */
    public Forum getForum() {
        return forum;
    }

    /**
     * Sets a forum to which this forum belongs
     *
     * @param forum forum to set as owner
     */
    public void setForum(Forum forum) {
        this.forum = forum;
    }

    /**
     * Returns first topic post.
     *
     * @return first post
     */
    public Post getFirstPost() {
        return firstPost;
    }

    /**
     * Sets first topic post.
     *
     * @param firstPost post to set
     */
    public void setFirstPost(Post firstPost) {
        this.firstPost = firstPost;
    }

    /**
     * Returns list of posts which belong to this topic.
     *
     * @return list of posts
     * @hibernate.bag name="posts" inverse="true" lazy="true" cascade="delete"
     * outer-join="false"
	 * @hibernate.collection-key column="`topic_id`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.forum.Post"
     */
    public List getPosts() {
        return posts;
    }

    /**
     * Sets list of posts
     *
     * @param posts list to set
     */
    public void setPosts(List posts) {
        this.posts = posts;
    }

    /**
     * Adds a post.
     *
     * @param post post to add
     */
    public void addPost(Post post) {
        this.posts.add(post);
        post.setTopic(this);
    }

    /**
     * Updates changed post.
     *
     * @param post post to be updated
     * @return post that has been replaced
     */
	public Post updatePost(Post post) {
        Post oldPost = null;
		if ( !post.getTopic().equals(this) ) {
            int index = post.getTopic().posts.indexOf(post);
            if (index != -1)
                oldPost = (Post) post.getTopic().posts.remove(index);
			posts.add(post);
			post.setTopic(this);
		}
        return oldPost;
	}

    /**
     * Removes a post.
     *
     * @param post post to remove
     */
    public void removePost(Post post) {
        this.posts.remove(post);
    }

    /**
     * Returns topic version
     *
     * @return version
     * @struts.form-field
	 * @hibernate.version column="`version`" type="long" unsaved-value="null"
     */
    public Long getVersion() {
        return version;
    }

    /**
     * Sets topic version
     *
     * @param version version to set
     */
    public void setVersion(Long version) {
        this.version = version;
    }

    /**
     * Returns number of replies in this topic (all posts except first one).
     *
     * @return number of replies
     */
    public Integer getNumberOfReplies() {
        return numberOfReplies;
    }

    /**
     * Sets number of replies in this topic.
     *
     * @param numberOfReplies number of replies to set
     */
    public void setNumberOfReplies(Integer numberOfReplies) {
        this.numberOfReplies = numberOfReplies;
    }

    /**
     * Returns last reply in this topic.
     *
     * @return last reply
     */
    public Post getLastReply() {
        return lastReply;
    }

    /**
     * Sets last reply in this topic.
     *
     * @param lastReply last reply to set
     */
    public void setLastReply(Post lastReply) {
        this.lastReply = lastReply;
    }

    /**
     * Returns first post subject (if there's no first post, <code>null</code>
     * is returned).
     *
     * @return first post subject
     */
    public String getFirstPostSubject() {
        String result = null;
        Post firstPost = getFirstPost();
        if (firstPost != null) {
            result = firstPost.getSubject();
        }
        return  result;
    }

    /**
     * Returns subscribed users map.
     *
     * @return subscribed users map
     * @see #usersSubscribed
     */
    public Map getUsersSubscribed() {
        return usersSubscribed;
    }

    /**
     * Sets subscribed users map.
     *
     * @param usersSubscribed map to set
     * @see #usersSubscribed
     */
    public void setUsersSubscribed(Map usersSubscribed) {
        this.usersSubscribed = usersSubscribed;
    }

    /**
     * Returns list of forum subscriptions.
     *
     * @return list of forum subscriptions
     * @hibernate.bag name="forumSubscriptions" inverse="true" lazy="true"
     * cascade="delete" outer-join="false"
	 * @hibernate.collection-key column="`topic_id`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.forum.ForumSubscription"
     */
    public List getForumSubscriptions() {
        return forumSubscriptions;
    }

    /**
     * Sets list of forum subscriptions.
     *
     * @param forumSubscriptions list to set
     */
    public void setForumSubscriptions(List forumSubscriptions) {
        this.forumSubscriptions = forumSubscriptions;
    }

    /**
     * Adds a forum subscription to the list.
     *
     * @param forumSubscription the subscription to be added
     */
	public void addForumSubscription(ForumSubscription forumSubscription) {
		forumSubscription.setTopic(this);
		forumSubscriptions.add(forumSubscription);
	}

    /**
     * Removes a forum subscription from the list.
     *
     * @param forumSubscription the subscription to be removed
     */
	public void removeForumSubscription(ForumSubscription forumSubscription) {
		forumSubscriptions.remove(forumSubscription);
	}

/*
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Topic)) return false;

        final Topic topic = (Topic) o;

        if (getFirstPostSubject() != null ? !getFirstPostSubject().equals(topic.getFirstPostSubject()) : topic.getFirstPostSubject() != null) return false;
        if (forum != null ? !forum.equals(topic.forum) : topic.forum != null) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = (forum != null ? forum.hashCode() : 0);
        result = 29 * result + (getFirstPostSubject() != null ? getFirstPostSubject().hashCode() : 0);
        return result;
    }
*/

    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Topic)) return false;

        final Topic topic = (Topic) o;

        if (forum != null ? !forum.equals(topic.forum) : topic.forum != null) return false;

        return true;
    }

    public int hashCode() {
        return (forum != null ? forum.hashCode() : 0);
    }
}
